#include "menu.h"
#include <stdio.h>

struct menu_data {
	Nodeptr         cursor;
	unsigned int    size;
	/* in case I need something :p */
};


struct menu_node {
	char            data[20];
	Nodeptr         next;
	Nodeptr         previous;
	Nodeptr         up;
	Nodeptr         down;
	unsigned int    sublist_size;
};

menu 
create(void)
{
	menu            new;
	new = malloc(sizeof(struct menu_data));
	if (new == NULL)
		return NULL;
	new->cursor = NULL;
	new->size = 0;
	return new;
}


bool 
empty(menu target_menu)
{
	if (target_menu->size == 0)
		return true;
	return false;
}



bool 
insert_node(menu target_menu, char data[20])
{
	Nodeptr         new;
	new = malloc(sizeof(struct menu_node));
	if (new == NULL)
		return false;
	strcpy(new->data, data);
	new->sublist_size = 0;
	new->up = new->down = NULL;
	if (target_menu->size == 0) {
		target_menu->cursor = new;
		new->next = new->previous = NULL;
	} else if (target_menu->cursor->next == NULL) {
		new->previous = target_menu->cursor;
		new->next = NULL;
		target_menu->cursor->next = new;
	} else {
		new->previous = target_menu->cursor;
		new->next = target_menu->cursor->next;
		target_menu->cursor->next->previous = new;
		target_menu->cursor->next = new;
	}
	target_menu->size++;
	return true;
}



bool 
insert_subnode(menu target_menu, char data[20])
{
	Nodeptr         new;
	if (empty(target_menu) == true)
		return false;
	new = malloc(sizeof(struct menu_node));
	if (new == NULL)
		return false;
	strcpy(new->data, data);
	new->next = new->previous = new->down = NULL;
	target_menu->cursor->down = new;
	new->up = target_menu->cursor;
	target_menu->cursor->sublist_size++;
	target_menu->size++;
	return true;
}




void 
delete_node(menu target_menu)
{
	Nodeptr         temp;
	unsigned int    size = 0;
	if (target_menu->cursor == NULL) {
		printf("Menu is empty!\n");
		return;
	}
	next(target_menu);
	if (target_menu->cursor->down != NULL)
		delete_sublevel(target_menu->cursor, size);
	/* fuction which deletes the current node */
	if (target_menu->cursor->previous != NULL)
		target_menu->cursor->previous->next = target_menu->cursor->next;
	if (target_menu->cursor->next != NULL)
		target_menu->cursor->next->previous = target_menu->cursor->previous;
	temp = target_menu->cursor;
	previous(target_menu);
	free(temp);
	target_menu->size--;
	target_menu -= size;
}

void 
delete_sublevel(Nodeptr node, unsigned int size)
{
	Nodeptr         temp, temp1;
	bool            up, back;
	temp = node->down;
	size = 0;
	while (temp != node && temp != NULL) {
		if (temp->down != NULL)
			temp = temp->down;
		else if (temp->next != NULL)
			temp = temp->next;
		else if (temp->next == NULL) {
			temp1 = temp;
			if (temp->previous != NULL) {
				back = true;
				temp = temp->previous;
			} else {
				up = true;
				temp = temp->up;
			}
			free(temp1);
			size++;
			if (back)
				temp->next = NULL;
			else
				temp->down = NULL;
		} else if (temp->down == NULL) {
			temp1 = temp;
			temp = temp->up;
			free(temp1);
			size++;
			temp->down = NULL;
		}
		up = back = false;
	}
}



void 
change_nodes(menu target_menu)
{
	Nodeptr         temp, previous;
	if (target_menu->cursor == NULL) {
		printf("Menu is empty!\n");
		return;
	}
	if (target_menu->cursor->next == NULL)
		return;
	temp = target_menu->cursor->next;
	target_menu->cursor->next = target_menu->cursor->next->next;
	if (target_menu->cursor->next != NULL)
		target_menu->cursor->next->previous = target_menu->cursor;
	previous = target_menu->cursor->previous;
	target_menu->cursor->previous = temp;
	temp->next = target_menu->cursor;
	temp->previous = previous;
	if (temp->previous != NULL)
		temp->previous->next = temp;
}






void 
next(menu target_menu)
{
	if (target_menu->cursor == NULL)
		return;
	if (target_menu->cursor->next != NULL)
		target_menu->cursor = target_menu->cursor->next;
}


void 
previous(menu target_menu)
{
	if (target_menu->cursor == NULL)
		return;
	if (target_menu->cursor->previous != NULL)
		target_menu->cursor = target_menu->cursor->previous;
}


void 
up(menu target_menu)
{
	if (target_menu->cursor == NULL)
		return;
	if (target_menu->cursor->up != NULL)
		target_menu->cursor = target_menu->cursor->up;
}



void 
down(menu target_menu)
{
	if (target_menu->cursor == NULL)
		return;
	if (target_menu->cursor->down != NULL)
		target_menu->cursor = target_menu->cursor->down;
}


void 
print(menu target_menu)
{
	if (target_menu->cursor == NULL) {
		printf("Menu is empty!\n");
		return;
	}
	printf("%s\n", target_menu->cursor->data);
}

static unsigned int tabs = 1;


void 
print_sublevel(menu target_menu)
{
	Nodeptr         temp;
	int             i;
	if (target_menu->cursor == NULL) {
		printf("Menu is empty!\n");
		return;
	}
	temp = target_menu->cursor->down;
	while (temp != NULL) {
		for (i = 0; i < tabs; i++)
			printf("  ");
		printf("%s \n", temp->data);
		if (temp->down != NULL) {
			menu            temp_menu = create();
			temp_menu->cursor = temp;
			tabs++;
			print_sublevel(temp_menu);
			tabs--;
			destroy(temp_menu);
		}
		temp = temp->next;
	}
}





void 
print_level(menu target_menu)
{
	Nodeptr         temp = target_menu->cursor;
	if (target_menu->cursor == NULL) {
		printf("Menu is empty!\n");
		return;
	}
	while (temp != NULL) {
		printf("%s\n", temp->data);
		temp = temp->next;
	}
}

void 
destroy(menu target_menu)
{
	Nodeptr         temp = target_menu->cursor, delete;
	unsigned int    size;
	if (target_menu->cursor == NULL) {
		printf("Menu is empty!\n");
		return;
	}
	while (temp != NULL) {
		delete_sublevel(temp, size);
		delete = temp;
		temp = temp->next;
		free(delete);
	}
	free(target_menu);
}

bool 
change(menu target_menu, char data[20])
{
	if (target_menu->cursor == NULL) {
		printf("Menu is empty!\n");
		return false;
	}
	strcpy(target_menu->cursor->data, data);
	return true;
}



void 
print_menu(menu target_menu)
{
	Nodeptr         start = target_menu->cursor;
	if (target_menu->cursor == NULL) {
		printf("Menu is empty!\n");
		return;
	}
	while (target_menu->cursor->next != NULL) {
		print(target_menu);
		print_sublevel(target_menu);
		next(target_menu);
	}
	print(target_menu);
	print_sublevel(target_menu);
	target_menu->cursor = start;
}
